package engine.light;

import java.util.ArrayList;
import java.util.Collections;

import engine.scene.Scene;

import static org.lwjgl.opengl.GL11.*;

public class LightManager {

	private Scene scene;
	
	private int maxLights;
	
	private ArrayList<EnvironmentLight> directionalLights;
	private ArrayList<PointLight> positionalLights;
	
	public LightManager(Scene scene) {
		this.scene = scene;
		
		directionalLights = new ArrayList<EnvironmentLight>();
		positionalLights = new ArrayList<PointLight>();
		
		maxLights = glGetInteger(GL_MAX_LIGHTS);
	}
	
	public void add(Light light) {
		if(light instanceof EnvironmentLight) {
			if(directionalLights.size() == maxLights) {
				throw new ArrayIndexOutOfBoundsException("There are too many environmental lights");
			}
			
			directionalLights.add((EnvironmentLight) light);
		}
		
		if(light instanceof PointLight) {
			positionalLights.add((PointLight) light);
		}
	}
	
	public void remove(Light light) {
		directionalLights.remove(light);
		positionalLights.remove(light);
	}
	
	public void applyLights() {
		int lightSource = GL_LIGHT0;
		
		for(EnvironmentLight e: directionalLights) {
			if(e.isEnable()) {
				e.apply(lightSource);
				lightSource++;
			}
		}
		
		//order positional lights
		if(scene.getCurrentCamera() != null) {
			for(PointLight p: positionalLights) {
				p.setPriority((p.getPosition().get(0) - scene.getCurrentCamera().getEyeX()) * (p.getPosition().get(0) - scene.getCurrentCamera().getEyeX()) + 
				(p.getPosition().get(1) - scene.getCurrentCamera().getEyeY()) * (p.getPosition().get(1) - scene.getCurrentCamera().getEyeY()) + 
				(p.getPosition().get(2) - scene.getCurrentCamera().getEyeZ()) * (p.getPosition().get(2) - scene.getCurrentCamera().getEyeZ()));
			}
		}
		Collections.sort(positionalLights);
		
		for(PointLight p: positionalLights) {
			if(lightSource > GL_LIGHT0 + maxLights) {
				break;
			}
			
			if(p.isEnable()) {
				p.apply(lightSource);
				lightSource++;
			}
		}
		
		for(int i = lightSource; i < GL_LIGHT0 + maxLights; i++) {
			glDisable(lightSource);
		}
	}
}
